<?php
/**
 * orm orm
 * @package common_lib_orm
 */
load_lib('/db/pooling');
load_lib('/cache/pooling');
/**
 * orm orm
 * @author pandajingjing
 * @todo 支持事务
 * @package common_lib_orm
 */
abstract class orm_orm{

	/**
	 * 所有执行的SQL语句
	 * @var array
	 */
	protected static $_arrSQLs=array();

	/**
	 * 数据库操作次数 
	 * @var int
	 */
	protected static $_intQueryCnt=0;

	/**
	 * 缓存操作次数
	 * @var int
	 */
	protected static $_intCacheCnt=0;

	/**
	 * PHP静态变量缓存
	 * @var array
	 */
	protected static $_arrStaticCache=array();

	/**
	 * 有Sequence的表
	 * @var array
	 */
	protected static $_arrSeqTbl=array();

	/**
	 * 数据库连接池
	 * @var array
	 */
	protected static $_arrDBPool=array();

	/**
	 * 数据库陈述
	 * @var object
	 */
	protected static $_objDBSTMT=NULL;

	/**
	 * 缓存连接
	 * @var object
	 */
	protected static $_objCache=NULL;

	/**
	 * 调试对象
	 * @var object
	 */
	protected static $_objDebug=NULL;

	/**
	 * 是否开启Debug信息
	 * @var boolean
	 */
	protected static $_bolDebug=false;

	/**
	 * 用于保存调试信息
	 * @var mix
	 */
	protected static $_mixDebugResult=NULL;

	/**
	 * 变量绑定占位符
	 * @var string
	 */
	protected static $_strBindHolder=':';

	/**
	 * ORM数据
	 * @var array
	 */
	protected $_arrData=array();

	/**
	 * ORM名称
	 * @var string
	 */
	protected $_strClassName=NULL;

	/**
	 * 数据库表结构
	 * @var array
	 */
	protected $_arrTblField=array();

	/**
	 * 调用APC的表数据
	 * @var array
	 */
	protected $_arrAPCTbl=array();

	/**
	 * 主键字段
	 * @var string
	 */
	protected $_strPKIDField=NULL;

	/**
	 * 表名称
	 * @var string
	 */
	protected $_strTblName=NULL;

	/**
	 * Master数据库连接名,在子类中配置
	 * @var string
	 */
	protected $_strMasterDBName=NULL;

	/**
	 * Slave数据库连接名,在子类中配置
	 * @var string
	 */
	protected $_strSlaveDBName=NULL;

	/**
	 * 是否开启缓存
	 * @var $_bolNeedCache
	 */
	protected $_bolNeedCache=false;

	/**
	 * 表结构缓存时间
	 * @var int
	 */
	protected $_intTblFieldCacheTime=0;

	/**
	 * 表结构缓存是否压缩
	 * @var int
	 */
	protected $_intTblFieldCacheCompress=MEMCACHE_COMPRESSED;

	/**
	 * 数据缓存时间
	 * @var int
	 */
	protected $_intDataCacheTime=86400;

	/**
	 * 数据缓存是否压缩
	 * @var int
	 */
	protected $_intDataCacheCompress=0;
	
	/**
	 * 排序
	 * @var string
	 */
	protected $_strOrder='';
	
	/**
	 * 开始行数
	 * @var int
	 */
	protected $_intStartRow=0;
	
	/**
	 * 获取行数
	 * @var int
	 */	
	protected $_intFetchRow=0;

	/**
	 * 创建实例
	 * @param string $p_strTblName
	 * @param boolean $p_bolStrictMaster
	 */
	function __construct($p_strTblName,$p_bolStrictMaster=false){
		$this->_strClassName=get_class($this);
		self::$_objDebug=sys_debugger::getInstance();
		self::$_bolDebug=self::$_objDebug->canDebug();
		$this->_strTblName=$p_strTblName;
		$this->_getTblField();
		if($p_bolStrictMaster){
			$this->_strSlaveDBName=$this->_strMasterDBName;
		}
	}

	/**
	 * 析构实例
	 */
	function __destruct(){
		self::$_objDebug->showMsg($this->_strClassName.'[ORM]->Query time: '.self::$_intQueryCnt.'. Cache time: '.self::$_intCacheCnt);
	}

	function __set($p_strField,$p_mixValue){
		$strField=strtoupper($p_strField);
		if(isset($this->_arrTblField[$strField])){
			$o_strOperator=$o_intParam='';
			if(!self::_isSelfOperate($p_strField,$p_mixValue,$o_strOperator,$o_intParam)){
				if('i'==$this->_arrTblField[$strField]['TYPE'] or 'f'==$this->_arrTblField[$strField]['TYPE']){
					if(!is_numeric($p_mixValue)){
						if($this->_arrTblField[$strField]['NULLABLE'] and ''==$p_mixValue){

						}else{
							throw new Exception('You set an illegal attribute('.$p_strField.') to ORM instance.Needed is number, maybe is '.gettype($p_mixValue).'(\''.print_r($p_mixValue,true).'\').');
							return false;
						}
					}
				}
				if(isset($this->_arrTblField[$strField]['LENGTH']) and 0<$this->_arrTblField[$strField]['LENGTH']){
					if('s'==$this->_arrTblField[$strField]['TYPE']){
						$intLength=mb_strlen($p_mixValue,get_config('charset'));
					}else{
						$intLength=strlen($p_mixValue);
					}
					if($intLength>$this->_arrTblField[$strField]['LENGTH']){
						throw new Exception('You set an attribute('.$p_strField.') out of DB settings to ORM instance.Max is '.$this->_arrTblField[$strField]['LENGTH'].', actually is '.$intLength.'.');
						return false;
					}
				}
			}
			$this->_arrData[$strField]=$p_mixValue;
		}else{
			throw new Exception($this->_strClassName.': you set an unexpected attribute('.$p_strField.') to ORM instance.');
			return false;
		}
	}

	function __get($p_strField){
		$strField=strtoupper($p_strField);
		if(isset($this->_arrTblField[$strField])){
			if(isset($this->_arrData[$strField])){
				return $this->_arrData[$strField];
			}else{
				return NULL;
			}
		}else{
			throw new Exception($this->_strClassName.': you get an unexpected attribute('.$p_strField.') from ORM instance.');
			return false;
		}
	}

	function __isset($p_strField){
		return isset($this->_arrData[strtoupper($p_strField)]);
	}

	function __unset($p_strField){
		unset($this->_arrData[strtoupper($p_strField)]);
	}

	/**
	 * 得到所有执行的SQL语句
	 * @return array;
	 */
	static function getAllSQL(){
		return self::$_arrSQLs;
	}

	/**
	 * 返回数据库操作次数
	 * @return int
	 */
	static function getQueryCnt(){
		return self::$_intQueryCnt;
	}

	/**
	 * 返回缓存操作次数
	 * @return int
	 */
	static function getCacheCnt(){
		return self::$_intCacheCnt;
	}
	
	/**
	 * 设置排序
	 * @param string $p_strOrder
	 */
	function setOrder($p_strOrder){
		$this->_strOrder=$p_strOrder;
	}
	
	/**
	 * 设置开始行数
	 * @param int $p_intStart
	 */
	function setStart($p_intStart){
		$this->_intStartRow=$p_intStart;
	}

	/**
	 * 设置获取行数
	 * @param int $p_intRow
	 */
	function setRow($p_intRow){
		$this->_intFetchRow=$p_intRow;
	}
	
	/**
	 * 得到ORM的所有数据
	 * @return array
	 */
	function getSource(){
		return $this->_arrData;
	}

	/**
	 * 设置ORM缓存时间
	 * @param int $p_intSecond
	 */
	function setCacheTime($p_intSecond){
		$this->_intDataCacheTime=$p_intSecond;
	}

	/**
	 * 设置ORM缓存内容是否压缩
	 * @param int $p_intCompress
	 */
	function setCacheCompress($p_intCompress){
		$this->_intDataCacheCompress=$p_intCompress;
	}

	/**
	 * 关闭缓存功能
	 */
	function disableCache(){
		$this->_bolNeedCache=false;
	}

	/**
	 * 根据主键删除ORM单行缓存
	 * @param int $p_intPKID
	 * @return true/false
	 */
	function clearRowCache($p_intPKID){
		return self::_clearCacheData(self::_getCacheRowKey($this->_strClassName,$this->_strTblName,$this->_strPKIDField,$p_intPKID));
	}

	/**
	 * 添加数据
	 * @return int/false
	 */
	function addData(){
		$arrSQLParam=self::_joinAddString($this->_arrTblField,$this->_arrData);
		$strSQL='insert into '.$this->_strTblName.' ('.$arrSQLParam['FIELDSSTR'].')values('.$arrSQLParam['PARAMSTR'].')';
		return self::_insertDBData($strSQL,$arrSQLParam['VALUEARR'],$this->_strMasterDBName,$this->_strClassName);
	}

	/**
	 * 更新数据
	 * @return int
	 */
	function updData(){
		$arrNewData=$this->getSource();
		$arrOldData=$this->getRow();
		foreach($arrNewData as $strField=>$strValue){
			if($strField!=$this->_strPKIDField and $strValue==$arrOldData[$strField]){
				unset($arrNewData[$strField]);
			}
		}
		if(1==count($arrNewData)){
			return 0;
		}
		$arrSQLParam=self::_joinUpdString($this->_arrTblField,$arrNewData,$this->_strPKIDField);
		$arrPKParam=self::_joinPKWhereString($this->_strPKIDField,$arrNewData);
		$strSQL='update '.$this->_strTblName.' set '.$arrSQLParam['FIELDSSTR'].' where '.$arrPKParam['FIELDSSTR'];
		$arrSQLParam['VALUEARR']=array_merge($arrSQLParam['VALUEARR'],$arrPKParam['VALUEARR']);
		$this->clearRowCache($arrPKParam['VALUEARR'][$this->_strPKIDField]);
		return self::_updDBData($strSQL,$arrSQLParam['VALUEARR'],$this->_strMasterDBName,$this->_strClassName);
	}

	/**
	 * 删除数据
	 * @return int
	 */
	function delData(){
		$arrPKParam=self::_joinPKWhereString($this->_strPKIDField,$this->_arrData);
		$strSQL='delete from '.$this->_strTblName.' where '.$arrPKParam['FIELDSSTR'];
		$this->clearRowCache($arrPKParam['VALUEARR'][$this->_strPKIDField]);
		return $this->_updDBData($strSQL,$arrPKParam['VALUEARR']);
	}

	/**
	 * 获取一行数据
	 * @param boolean $p_bolStrictFreshCache
	 * @return array/NULL
	 */
	function getRow($p_bolStrictFreshCache=false){
		$arrPKParam=self::_joinPKWhereString($this->_strPKIDField,$this->_arrData);
		$strCacheKey=self::_getCacheRowKey($this->_strClassName,$this->_strTblName,$this->_strPKIDField,$arrPKParam['VALUEARR'][$this->_strPKIDField]);
		if($p_bolStrictFreshCache or !$this->_bolNeedCache){
			$arrData=false;
		}else{
			$arrData=$this->_getCacheData($strCacheKey);
		}
		if(false===$arrData){
			$strSQL='select '.self::_joinSelectString($this->_arrTblField).' from '.$this->_strTblName.' where '.$arrPKParam['FIELDSSTR'];
			$arrData=$this->_getDBData($strSQL,$arrPKParam['VALUEARR'],2);
			if(NULL===$arrData){
				return NULL;
			}
			$this->_arrData=$arrData;
			$this->_setCacheData($strCacheKey,$arrData);
		}else{
			$this->_arrData=$arrData;
		}
		return $this->_arrData;
	}

	/**
	 * 获取多行数据
	 * @param string $p_strWhere
	 * @param array $p_arrParam
	 * @param boolean $p_bolStrictFreshCache
	 * @return array
	 */
	function getList($p_strWhere='',$p_arrParam=array(),$p_bolStrictFreshCache=false){
		$strSQL='select '.$this->_strPKIDField.' from '.$this->_strTblName;
		if(''!=$p_strWhere){
			$strSQL.=' where '.$p_strWhere;
		}
		if(''!=$this->_strOrder){
			$strSQL.=' order by '.$this->_strOrder;
			$this->_strOrder='';
		}
		if($this->_intFetchRow>0){
			if($this->_intStartRow>0){
				$strSQL.=' limit '.$this->_intStartRow.','.$this->_intFetchRow;
				$this->_intStartRow=0;
			}else{
				$strSQL.=' limit '.$this->_intFetchRow;
			}
			$this->_intFetchRow=0;
		}
		$arrPKIDs=$this->_getDBData($strSQL,$p_arrParam,3);
		if(empty($arrPKIDs)){
			return array();
		}
		$intCnt=count($arrPKIDs);
		if(0<$intCnt){
			return $this->getListByPKIDs($arrPKIDs,$p_bolStrictFreshCache);
		}else{
			return array();
		}
	}

	/**
	 * 根据PKID获取数据
	 * @param mix $p_mixIDs
	 * @param boolean $p_bolStrictFreshCache
	 * @todo
	 * @return array
	 */
	function getListByPKIDs($p_mixIDs,$p_bolStrictFreshCache=false){
		$arrPKIDs=self::_rebuildPKIDs($p_mixIDs,$this->_strPKIDField);
		if(empty($arrPKIDs)){
			return array();
		}
		$arrRS=array();
		$intCntPKIDs=count($arrPKIDs);
		if($this->_bolNeedCache and !$p_bolStrictFreshCache){
			$arrCacheKey=array();
			$arrCacheRS=array();
			for($i=0;$i<$intCntPKIDs;++$i){
				$arrCacheKey[]=self::_getCacheRowKey($this->_strClassName,$this->_strTblName,$this->_strPKIDField,$arrPKIDs[$i]);
			}
			$arrCacheRS=$this->_getCacheData($arrCacheKey);
			$arrCacheMissIDs=array();
			for($i=0;$i<$intCntPKIDs;++$i){
				if(isset($arrCacheRS[$arrCacheKey[$i]])){

				}else{
					$arrCacheMissIDs[]=$arrCacheKey[$i];
				}
			}
			$intCacheMissIDsCnt=count($arrCacheMissIDs);
			if(0<$intCacheMissIDsCnt){
				$arrPKIDsPattern='';
				$arrParam=array();
				for($i=0;$i<$intCacheMissIDsCnt;++$i){
					$arrPKIDsPattern[]=self::$_strBindHolder.$this->_strPKIDField.'_'.$i;
					$arrParam[$this->_strPKIDField.'_'.$i]=$arrPKIDs[$i];
				}
				$strSQL='select '.self::_joinSelectString($this->_arrTblField).' from '.$this->_strTblName.' where '.$this->_strPKIDField.' in ('.join(' ,',$arrPKIDsPattern).')';
				$arrDBData=$this->_getDBData($strSQL,$arrParam,3);
				$intCntDBData=count($arrRS);
				for($i=0;$i<$intCntDBData;++$i){
					$this->_setCacheData(self::_getCacheRowKey($this->_strClassName,$this->_strTblName,$this->_strPKIDField,$arrDBData[$i][$this->_strPKIDField]),$arrDBData[$i]);
				}
			}
			/* for($i=0;$i<$intCntAllPKIDs;++$i){
				foreach($arrCacheDatas as $arrCacheData){
					$arrTmp=array();
					foreach($this->_strPKIDField as $strPKIDField){
						$arrTmp[$strPKIDField]=$arrCacheData[$strPKIDField];
					}
					if($arrAllPKIDs[$i]==$arrTmp){
						$arrRS[$i]=$arrCacheData;
						continue 2;
					}
				}
				for($k=0;$k<$intCacheMissIDsCnt;++$k){
					$arrTmp=array();
					foreach($this->_strPKIDField as $strPKIDField){
						$arrTmp[$strPKIDField]=$arrDBData[$k][$strPKIDField];
					}
					if($arrAllPKIDs[$i]==$arrTmp){
						$arrRS[$i]=$arrDBData[$k];
						continue 2;
					}
				}
			} */
		}else{
			$arrPKIDsPattern='';
			$arrParam=array();
			for($i=0;$i<$intCntPKIDs;++$i){
				$arrPKIDsPattern[]=self::$_strBindHolder.$this->_strPKIDField.'_'.$i;
				$arrParam[$this->_strPKIDField.'_'.$i]=$arrPKIDs[$i];
			}
			$strSQL='select '.self::_joinSelectString($this->_arrTblField).' from '.$this->_strTblName.' where '.$this->_strPKIDField.' in ('.join(' ,',$arrPKIDsPattern).')';
			$arrDBData=$this->_getDBData($strSQL,$arrParam,3);
			$intCntDBData=count($arrDBData);
			for($i=0;$i<$intCntDBData;++$i){
				$this->_setCacheData(self::_getCacheRowKey($this->_strClassName,$this->_strTblName,$this->_strPKIDField,$arrDBData[$i][$this->_strPKIDField]),$arrDBData[$i]);
			}
			for($i=0;$i<$intCntPKIDs;++$i){
				for($k=0;$k<$intCntDBData;++$k){
					if($arrPKIDs[$i]==$arrDBData[$k][$this->_strPKIDField]){
						$arrRS[$i]=$arrDBData[$k];
						continue 2;
					}
				}
			}
		}
		return $arrRS;
	}

	/**
	 * 得到统计数据
	 * @param string $p_strWhere
	 * @param array $p_arrParam
	 * @param boolean $p_bolStrictFreshCache
	 * @return int
	 */
	function getCnt($p_strWhere='',$p_arrParam=array(),$p_bolStrictFreshCache=false){
		$strSQL='select count(*) as cnt from '.$this->_strTblName;
		if(''!=$p_strWhere){
			$strSQL.=' where '.$p_strWhere;
		}
		return $this->_getDBData($strSQL,$p_arrParam,1);
	}

	/**
	 * 批量更新数据
	 * @param string $p_strWhere
	 * @param array $p_arrParam
	 * @return int
	 */
	function updList($p_strWhere,$p_arrParam=array()){
		$strSQL='select '.$this->_strPKIDField.' from '.$this->_strTblName;
		if(''!=$p_strWhere){
			$strSQL.=' where '.$p_strWhere;
		}
		$arrPKIDs=$this->_getDBData($strSQL,$p_arrParam,3);
		$intCnt=count($arrPKIDs);
		if(0<$intCnt){
			return $this->updListByPKIDs($arrPKIDs);
		}else{
			return 0;
		}
	}

	/**
	 * 根据PKID更新数据
	 * @param mix $p_mixIDs
	 * @return int
	 */
	function updListByPKIDs($p_mixIDs){
		$arrPKIDs=self::_rebuildPKIDs($p_mixIDs,$this->_strPKIDField);
		if(empty($arrPKIDs)){
			return array();
		}
		$intCnt=count($arrPKIDs);
		$arrSQLParam=self::_joinUpdString($this->_arrTblField,$this->_arrData,$this->_strPKIDField);
		$arrPKIDsPattern='';
		$arrParam=array();
		for($i=0;$i<$intCnt;++$i){
			$this->clearRowCache($arrPKIDs[$i]);
			$arrPKIDsPattern[]=self::$_strBindHolder.$this->_strPKIDField.'_'.$i;
			$arrParam[$this->_strPKIDField.'_'.$i]=$arrPKIDs[$i];
		}
		$strSQL='update '.$this->_strTblName.' set '.$arrSQLParam['FIELDSSTR'].' where '.$this->_strPKIDField.' in ('.join(' ,',$arrPKIDsPattern).')';
		return $this->_updDBData($strSQL,array_merge($arrSQLParam['VALUEARR'],$arrParam));
	}

	/**
	 * 执行SQL
	 * @param string $p_strSQL
	 * @param array $p_arrParam
	 * @param string $p_strFetchType
	 * @return array/string
	 */
	function executeSQL($p_strSQL,$p_arrParam=array(),$p_strFetchType='all'){
		$arrSQLInfo=array();
		if(preg_match('/^(insert|update|delete|select)/i',$p_strSQL,$arrSQLInfo)){
			$strSQLType=strtolower($arrSQLInfo[1]);
			switch($strSQLType){
				case 'insert':
					return $this->_insertDBData($p_strSQL,$p_arrParam);
					break;
				case 'delete':
				case 'update':
					return $this->_updDBData($p_strSQL,$p_arrParam);
					break;
				case 'select':
					switch(strtolower($p_strFetchType)){
						case 'one':
							return $this->_getDBData($p_strSQL,$p_arrParam,1);
							break;
						case 'row':
							return $this->_getDBData($p_strSQL,$p_arrParam,2);
							break;
						case 'all':
						default:
							return $this->_getDBData($p_strSQL,$p_arrParam,3);
					}
					break;
				default:
					throw new Exception('Illegal SQL: '.$p_strSQL);
					return false;
			}
		}else{
			throw new Exception('Illegal SQL: '.$p_strSQL);
		}
	}

	/**
	 * 返回数据库表结构
	 */
	private function _getTblField(){
		$strTblFieldCacheKey=self::_getTblFieldCacheKey($this->_strClassName,$this->_strTblName);
		$arrTblField=$this->_getCacheData($strTblFieldCacheKey);
		if(false===$arrTblField){
			$arrTblField=self::_getDBData('desc '.$this->_strTblName,array(),3);
			self::_setCacheData($strTblFieldCacheKey,$arrTblField,7);
		}
		foreach($arrTblField as $arrFieldSet){
			$arrTmpFieldInfo=self::_field2ORMField($arrFieldSet['Type']);
			$this->_arrTblField[strtoupper($arrFieldSet['Field'])]=array( 
					'TYPE'=>$arrTmpFieldInfo['TYPE'],
					'PDOTYPE'=>$arrTmpFieldInfo['PDOTYPE'],
					'LENGTH'=>isset($arrTmpFieldInfo['LENGTH'])?$arrTmpFieldInfo['LENGTH']:0,
					'NULLABLE'=>('YES'==$arrFieldSet['Null']?true:false) 
			);
			if('PRI'==$arrFieldSet['Key']){
				if(NULL===$this->_strPKIDField){
					$this->_strPKIDField=strtoupper($arrFieldSet['Field']);
				}else{
					throw new Exception('Table('.$this->_strTblName.') is not accessible for ORM(Too many primary key).');
					return false;
				}
			}
		}
		if(!isset($this->_strPKIDField[0])){
			throw new Exception('Table('.$this->_strTblName.') is not accessible for ORM(No primary key).');
			return false;
		}
	}

	/**
	 * 获取缓存连接
	 */
	private static function _connectCache(){
		if(NULL==self::$_objCache){
			self::$_objCache=cache_pooling::getInstance()->getCache();
		}
	}

	/**
	 * 获取数据库连接
	 * @param string 数据库连接名
	 */
	private static function _connectDB($p_strDBName){
		if(isset(self::$_arrDBPool[$p_strDBName])){

		}else{
			self::$_arrDBPool[$p_strDBName]=db_pooling::getInstance()->getConnect($p_strDBName);
		}
	}

	/**
	 * 根据Key删除缓存
	 * @param string $p_strCacheKey
	 * @return true/false
	 */
	private function _clearCacheData($p_strCacheKey){
		++self::$_intCacheCnt;
		$this->_clearStaticCacheData($p_strCacheKey);
		$this->_clearAPCCacheData($p_strCacheKey);
		return $this->_clearMemCacheData($p_strCacheKey);
	}

	/**
	 * 根据Key删除静态缓存
	 * @param string $p_strCacheKey
	 * @return true
	 */
	private function _clearStaticCacheData($p_strCacheKey){
		if(isset(self::$_arrStaticCache[$p_strCacheKey])){
			unset(self::$_arrStaticCache[$p_strCacheKey]);
			self::$_mixDebugResult=true;
		}else{
			self::$_mixDebugResult=false;
		}
		if(self::$_bolDebug){
			self::$_objDebug->showMsg($this->_strClassName.'[StaticCache]->Delete: '.$p_strCacheKey.'|'.var_export(self::$_mixDebugResult,true));
		}
		return true;
	}

	/**
	 * 根据Key删除APC缓存
	 * @param string $p_strCacheKey
	 */
	private function _clearAPCCacheData($p_strCacheKey){

	}

	/**
	 * 根据Key删除Memcache
	 * @param string $p_strCacheKey
	 * @return true/false
	 */
	private function _clearMemCacheData($p_strCacheKey){
		self::_connectCache();
		for($i=0;$i<5;++$i){
			self::$_mixDebugResult=self::$_objCache->delete($p_strCacheKey,0);
			if(true===self::$_mixDebugResult){
				break;
			}
		}
		if(self::$_bolDebug){
			self::$_objDebug->showMsg($this->_strClassName.'[Memcache]->Delete: '.$p_strCacheKey.'|'.var_export(self::$_mixDebugResult,true));
		}
		return self::$_mixDebugResult;
	}

	/**
	 * 写入缓存数据
	 * @param string $p_strKey
	 * @param mix $p_mixData
	 * @param int $p_intDeepLevel 1-static, 2-apc, 4-memcache
	 */
	private function _setCacheData($p_strCacheKey,$p_mixData,$p_intDeepLevel=1){
		++self::$_intCacheCnt;
		if(0x04===($p_intDeepLevel&0x04)){
			$this->_setStaticCacheData($p_strCacheKey,$p_mixData);
		}
		if(0x02===($p_intDeepLevel&0x02)){
			$this->_setAPCCacheData($p_strCacheKey,$p_mixData);
		}
		if(0x01===($p_intDeepLevel&0x01)){
			$this->_setMemCacheData($p_strCacheKey,$p_mixData);
		}
	}

	/**
	 * 写入静态缓存数据
	 * @param string $p_strCacheKey
	 * @param mix $p_mixData
	 */
	private function _setStaticCacheData($p_strCacheKey,$p_mixData){
		self::$_arrStaticCache[$p_strCacheKey]=$p_mixData;
		if(self::$_bolDebug){
			self::$_objDebug->showMsg($this->_strClassName.'[StaticCache]->Set: '.$p_strCacheKey.'|true');
		}
	}

	/**
	 * 写入APC缓存数据
	 * @param string $p_strCacheKey
	 * @param mix $p_mixData
	 */
	private function _setAPCCacheData($p_strCacheKey,$p_mixData){

	}

	/**
	 * 写入Memcache缓存数据
	 * @param string $p_strCacheKey
	 * @param mix $p_mixData
	 * @todo 批量缓存
	 */
	private function _setMemCacheData($p_strCacheKey,$p_mixData){
		self::_connectCache();
		$arrCacheData=self::_implodeCache($p_mixData,$this->_intDataCacheTime);
		for($i=0;$i<5;++$i){
			self::$_mixDebugResult=self::$_objCache->set($p_strCacheKey,$arrCacheData,$this->_intDataCacheCompress,$this->_intDataCacheTime);
			if(true===self::$_mixDebugResult){
				break;
			}
		}
		if(self::$_bolDebug){
			self::$_objDebug->showMsg($this->_strClassName.'[Memcache]->Set: '.$p_strCacheKey.'|'.var_export($p_mixData,true).'|'.var_export(self::$_mixDebugResult,true));
			if(false!==self::$_mixDebugResult){
				self::$_objDebug->showMsg($this->_strClassName.'[Memcache]->Info: Key=>'.$p_strCacheKey.' Create=>'.date('Y-m-d H:i:s',$arrCacheData['CREATETIME']).' Expire=>'.(0==$arrCacheData['LIFETIME']?'unlimit':date('Y-m-d H:i:s',$arrCacheData['CREATETIME']+$arrCacheData['LIFETIME'])));
			}
		}
	}

	/**
	 * 获取缓存数据
	 * @param mix $p_mixCacheKey
	 * @return mix
	 */
	private function _getCacheData($p_mixCacheKey){
		++self::$_intCacheCnt;
		if(is_array($p_mixCacheKey)){
			$intResultType=1; //数组
		}else{
			$intResultType=2; //单个 
			$p_mixCacheKey=array( 
					$p_mixCacheKey 
			);
		}
		$intCnt=count($p_mixCacheKey);
		$arrMissKey=array();
		$mixData=array();
		if(self::$_bolDebug){
			foreach($p_mixCacheKey as $strCacheKey){
				if(isset(self::$_arrStaticCache[$strCacheKey])){
					$mixData[$strCacheKey]=self::$_arrStaticCache[$strCacheKey];
					self::$_objDebug->showMsg($this->_strClassName.'[StaticCache]->Get: '.$strCacheKey.'|'.var_export(self::$_arrStaticCache[$strCacheKey],true));
				}else{
					$arrMissKey[]=$strCacheKey;
					self::$_objDebug->showMsg($this->_strClassName.'[StaticCache]->Get: '.$strCacheKey.'|false');
				}
			}
		}else{
			foreach($p_mixCacheKey as $strCacheKey){
				if(isset(self::$_arrStaticCache[$strCacheKey])){
					$mixData[$strCacheKey]=self::$_arrStaticCache[$strCacheKey];
				}else{
					$arrMissKey[]=$strCacheKey;
				}
			}
		}
		if(empty($arrMissKey)){
			if(1==$intResultType){
				return $mixData;
			}else{
				return $mixData[$p_mixCacheKey[0]];
			}
		}
		$intCnt=count($arrMissKey);
		self::_connectCache();
		$arrCacheData=self::$_objCache->get($arrMissKey);
		if(self::$_bolDebug){
			foreach($arrMissKey as $strCacheKey){
				if(isset($arrCacheData[$strCacheKey])){
					$arrEachCacheData=$arrCacheData[$strCacheKey];
					$mixData[$strCacheKey]=$arrEachCacheData['DATA'];
					self::$_objDebug->showMsg($this->_strClassName.'[Memcache]->Get: '.$strCacheKey.'|'.var_export($arrEachCacheData['DATA'],true));
					self::$_objDebug->showMsg($this->_strClassName.'[Memcache]->Info: Key=>'.$strCacheKey.' Create=>'.date('Y-m-d H:i:s',$arrEachCacheData['CREATETIME']).' Expire=>'.(0==$arrEachCacheData['LIFETIME']?'unlimit':date('Y-m-d H:i:s',$arrEachCacheData['CREATETIME']+$arrEachCacheData['LIFETIME'])));
					$this->_setStaticCacheData($strCacheKey,$arrEachCacheData['DATA']);
				}else{
					self::$_objDebug->showMsg($this->_strClassName.'[Memcache]->Get: '.$strCacheKey.'|false');
				}
			}
		}else{
			foreach($arrMissKey as $strCacheKey){
				if(isset($arrCacheData[$strCacheKey]) and false!==$arrCacheData[$strCacheKey]){
					$arrEachCacheData=$arrCacheData[$strCacheKey];
					$mixData[$strCacheKey]=$arrEachCacheData['DATA'];
					$this->_setStaticCacheData($strCacheKey,$arrEachCacheData['DATA']);
				}
			}
		}
		if(0==count($mixData)){
			return false;
		}else{
			if(1==$intResultType){
				return $mixData;
			}else{
				return $mixData[$p_mixCacheKey[0]];
			}
		}
	}

	/**
	 * 获取数据库数据
	 * @param string $p_strSQL
	 * @param array $p_arrParam
	 * @param int $p_intType 1-column, 2-row, 3-list
	 * @return array/string
	 */
	private function _getDBData($p_strSQL,$p_arrParam,$p_intType){
		self::_connectDB($this->_strSlaveDBName);
		self::$_arrSQLs[]=$p_strSQL;
		self::$_objDBSTMT=self::$_arrDBPool[$this->_strSlaveDBName]->prepare($p_strSQL);
		self::_bindData(self::_parseParameter($p_arrParam,$this->_arrTblField));
		self::$_objDBSTMT->execute();
		++self::$_intQueryCnt;
		self::$_objDBSTMT->setFetchMode(PDO::FETCH_ASSOC);
		switch($p_intType){
			case 1:
				$mixData=self::$_objDBSTMT->fetchColumn();
				break;
			case 2:
				$mixData=self::$_objDBSTMT->fetch();
				if(false===$mixData){
					$mixData=NULL;
				}
				break;
			case 3:
				$mixData=self::$_objDBSTMT->fetchAll();
				break;
		}
		if(self::$_bolDebug){
			self::$_objDebug->showMsg($this->_strClassName.'['.$this->_strSlaveDBName.']->Execute: '.$p_strSQL);
			self::$_objDebug->showMsg($this->_strClassName.'['.$this->_strSlaveDBName.']->Parameter: '.print_r($p_arrParam,true));
			self::$_objDebug->showMsg($this->_strClassName.'['.$this->_strSlaveDBName.']->Result: '.var_export($mixData,true));
		}
		return $mixData;
	}

	/**
	 * 更新数据库数据
	 * @param string $p_strSQL
	 * @param array $p_arrParam
	 * @return int
	 */
	private function _updDBData($p_strSQL,$p_arrParam){
		self::_connectDB($this->_strMasterDBName);
		self::$_arrSQLs[]=$p_strSQL;
		self::$_objDBSTMT=self::$_arrDBPool[$this->_strMasterDBName]->prepare($p_strSQL);
		self::_bindData(self::_parseParameter($p_arrParam,$this->_arrTblField));
		self::$_mixDebugResult=self::$_objDBSTMT->execute();
		++self::$_intQueryCnt;
		$intLastAffectedCnt=self::$_objDBSTMT->rowCount();
		if(self::$_bolDebug){
			self::$_objDebug->showMsg($this->_strClassName.'['.$this->_strMasterDBName.']->Execute: '.$p_strSQL);
			self::$_objDebug->showMsg($this->_strClassName.'['.$this->_strMasterDBName.']->Parameter: '.print_r($p_arrParam,true));
			self::$_objDebug->showMsg($this->_strClassName.'['.$this->_strMasterDBName.']->Result: '.var_export(self::$_mixDebugResult,true).'.<br />Affected row count: '.$intLastAffectedCnt,true);
		}
		return $intLastAffectedCnt;
	}

	/**
	 * 插入数据库数据
	 * @param string $p_strSQL
	 * @param array $p_arrParam
	 * @return int/false
	 */
	private function _insertDBData($p_strSQL,$p_arrParam){
		/*echo $p_strSQL;
		print_r($p_arrParam);
		$intSeqID=self::_getSeqNextValue();
		$arrTmp=array();
		preg_match('/insert into '.$this->_strTblName.'\s*\((.*)\)\s*values\s*\((.*)\)/i',$p_strSQL,$arrTmp);
		$p_strSQL='insert into '.$this->_strTblName.'('.$this->_strPKIDField.', '.$arrTmp[1].')values(:'.$this->_strPKIDField.', '.$arrTmp[2].')';
		$p_arrParam[$this->_strPKIDField]=$intSeqID;*/
		self::_connectDB($this->_strMasterDBName);
		self::$_arrSQLs[]=$p_strSQL;
		self::$_objDBSTMT=self::$_arrDBPool[$this->_strMasterDBName]->prepare($p_strSQL);
		self::_bindData(self::_parseParameter($p_arrParam,$this->_arrTblField));
		self::$_mixDebugResult=self::$_objDBSTMT->execute();
		++self::$_intQueryCnt;
		$intLastInsertID=self::$_arrDBPool[$this->_strMasterDBName]->lastInsertId();
		if(self::$_bolDebug){
			self::$_objDebug->showMsg($this->_strClassName.'['.$this->_strMasterDBName.']->Execute: '.$p_strSQL);
			self::$_objDebug->showMsg($this->_strClassName.'['.$this->_strMasterDBName.']->Parameter: '.print_r($p_arrParam,true));
			self::$_objDebug->showMsg($this->_strClassName.'['.$this->_strMasterDBName.']->Result: '.var_export(self::$_mixDebugResult,true).'.<br />LastID: '.$intLastInsertID,true);
		}
		return $intLastInsertID;
	}

	/**
	 * 获取主键值
	 * @todo getSeqNextValue 以后完成
	 * @return int
	 */
	private function _getSeqNextValue(){
		$strSeqDBName='seq_master';
		self::_connectDB($strSeqDBName);
		if(empty(self::$_arrSeqTable)){
			$strSeqTblKey='seq_tbl';
			$arrSeqTable=$this->_getCacheData($strSeqTblKey);
			if(false===$arrSeqTable){
				$strSQL='show tables';
				$bolGetSeq=false;
				self::$_arrSQLs[]=$strSQL;
				self::$_objDBSTMT=self::$_arrDBPool[$strSeqDBName]->prepare($strSQL);
				self::$_objDBSTMT->execute();
				++self::$_intQueryCnt;
				self::$_objDBSTMT->setFetchMode(PDO::FETCH_ASSOC);
				$mixData=self::$_objDBSTMT->fetchAll();
				if(self::$_bolDebug){
					self::$_objDebug->showMsg($this->_strClassName.'['.$strSeqDBName.']->Execute: '.$strSQL);
					self::$_objDebug->showMsg($this->_strClassName.'['.$strSeqDBName.']->Result: '.var_export($mixData,true));
				}
				$arrSeqTable=array();
				foreach($mixData as $arrTblName){
					$arrSeqTable[]=$arrTblName['Tables_in_seq_db'];
					if($this->_strTblName==$arrTblName['Tables_in_seq_db']){
						$bolGetSeq=true;
					}
				}
				$this->_setCacheData($strSeqTblKey,$arrSeqTable);
			}
		}else{
			foreach(self::$_arrSeqTbl as $strTblName){
				if($strTblName==$this->_strTblName){
					$bolGetSeq=true;
				}
			}
		}
		if($bolGetSeq){
			$strSQL='insert into '.$this->_strTblName.'(SEQNAME)values("'.$this->_strTblName.'") on duplicate key update SEQVALUE=LAST_INSERT_ID(SEQVALUE+1)';
			self::$_arrSQLs[]=$strSQL;
			self::$_objDBSTMT=self::$_arrDBPool[$strSeqDBName]->prepare($strSQL);
			self::$_mixDebugResult=self::$_objDBSTMT->execute();
			++self::$_intQueryCnt;
			$intLastInsertID=self::$_arrDBPool[$strSeqDBName]->lastInsertId();
			if(self::$_bolDebug){
				self::$_objDebug->showMsg($this->_strClassName.'['.$this->_strMasterDBName.']->Execute: '.$strSQL);
				self::$_objDebug->showMsg($this->_strClassName.'['.$this->_strMasterDBName.']->Parameter: '.print_r(array( 
						array( 
								'SEQNAME'=>$this->_strTblName 
						) 
				),true));
				self::$_objDebug->showMsg($this->_strClassName.'['.$this->_strMasterDBName.']->Result: '.var_export(self::$_mixDebugResult,true).'.<br />LastID: '.$intLastInsertID,true);
			}
			return $intLastInsertID;
		}else{
			return 0;
		}
	}

	/**
	 * 分析SQL参数
	 * @param array $p_arrParam
	 * @param array $p_arrTblFields
	 * @return array
	 */
	private static function _parseParameter($p_arrParam,$p_arrTblFields){
		$arrParam=array();
		foreach($p_arrParam as $strField=>$mixValue){
			$arrField=array();
			preg_match('/([a-zA-Z0-9]+)(\_\d)?/',$strField,$arrField);
			$arrParam[]=array( 
					'FIELD'=>$strField,
					'VALUE'=>$mixValue,
					'PDOTYPE'=>$p_arrTblFields[$arrField[1]]['PDOTYPE'],
					'LENGTH'=>$p_arrTblFields[$arrField[1]]['LENGTH'] 
			);
		}
		return $arrParam;
	}

	/**
	 * 绑定变量
	 * @param array $p_arrParam
	 */
	private static function _bindData($p_arrParam){
		$intCnt=count($p_arrParam);
		foreach($p_arrParam as $arrParam){
			$mixValue=$arrParam['VALUE'];
			self::$_objDBSTMT->bindParam(':'.$arrParam['FIELD'],$mixValue,$arrParam['PDOTYPE'],$arrParam['LENGTH']);
			unset($mixValue);
		}
	}

	/**
	 * mysql字段信息转换为ORM字段信息
	 * @param string $p_strField
	 * @return array
	 */
	private static function _field2ORMField($p_strField){
		$arrTmpFieldInfo=array();
		preg_match('/(int|char|varchar|text)\(?(\d*)\)?(unsigned)?/',$p_strField,$arrTmpFieldInfo);
		$arrFieldInfo=array();
		if(empty($arrTmpFieldInfo)){
			throw new Exception('Unknow field from Mysql('.$p_strField.').');
		}else{
			switch($arrTmpFieldInfo[1]){
				case 'int':
					$arrFieldInfo['TYPE']='i';
					$arrFieldInfo['LENGTH']=$arrTmpFieldInfo[2];
					$arrFieldInfo['PDOTYPE']=PDO::PARAM_INT;
					break;
				case 'char':
					$arrFieldInfo['TYPE']='s';
					$arrFieldInfo['LENGTH']=$arrTmpFieldInfo[2];
					$arrFieldInfo['PDOTYPE']=PDO::PARAM_STR;
					break;
				case 'varchar':
					$arrFieldInfo['TYPE']='s';
					$arrFieldInfo['LENGTH']=$arrTmpFieldInfo[2];
					$arrFieldInfo['PDOTYPE']=PDO::PARAM_STR;
					break;
				case 'text':
					$arrFieldInfo['TYPE']='s';
					$arrFieldInfo['LENGTH']=20000;
					$arrFieldInfo['PDOTYPE']=PDO::PARAM_LOB;
					break;
				default:
					throw new Exception('Unknow field from Mysql('.$p_strField.').');
					break;
			}
		}
		if(isset($arrTmpFieldInfo[3]) and 'unsigned'==$arrTmpFieldInfo[3]){
			++$arrFieldInfo['LENGTH'];
		}
		return $arrFieldInfo;
	}

	/**
	 * 获取ORM获取数据所需SQL信息
	 * @param array $p_arrTblFields
	 * @return string
	 */
	private static function _joinSelectString($p_arrTblFields){
		$strFields='';
		foreach($p_arrTblFields as $strField=>$arrFieldSet){
			$strFields.=', '.$strField;
		}
		if(isset($strFields[0])){
			return substr($strFields,2);
		}else{
			throw new Exception('ORM is illegally.');
			return false;
		}
	}

	/**
	 * 获取ORM添加信息所需SQL信息
	 * @param array $p_arrTblFields
	 * @param array $p_arrData
	 * @return array
	 */
	private static function _joinAddString($p_arrTblFields,$p_arrData){
		$strFields='';
		$strParams='';
		$arrValues='';
		foreach($p_arrTblFields as $strField=>$arrFieldSet){
			if(isset($p_arrData[$strField])){
				$strFields.=', '.$strField;
				$strParams.=', '.self::$_strBindHolder.$strField;
				$arrValues[$strField]=$p_arrData[$strField];
			}
		}
		if(isset($strFields[0])){
			return array( 
					'FIELDSSTR'=>substr($strFields,2),
					'PARAMSTR'=>substr($strParams,2),
					'VALUEARR'=>$arrValues 
			);
		}else{
			throw new Exception('ORM is illegally.');
			return false;
		}
	}

	/**
	 * 获取ORM更新信息所需SQL信息
	 * @param array $p_arrTblFields
	 * @param array $p_arrData
	 * @param string $p_strPKIDField
	 * @return array
	 */
	private static function _joinUpdString($p_arrTblFields,$p_arrData,$p_strPKIDField){
		$strFields='';
		$arrValues=array();
		foreach($p_arrTblFields as $strField=>$arrFieldSet){
			if($p_strPKIDField!=$strField and isset($p_arrData[$strField])){
				$strSelfOperator=$intSelfParam='';
				if(self::_isSelfOperate($strField,$p_arrData[$strField],$strSelfOperator,$intSelfParam)){
					$strFields.=', '.$strField.'='.$strField.$strSelfOperator.self::$_strBindHolder.$strField;
					$arrValues[$strField]=$intSelfParam;
				}else{
					$strFields.=', '.$strField.'='.self::$_strBindHolder.$strField;
					$arrValues[$strField]=$p_arrData[$strField];
				}
			}
		}
		if(isset($strFields[0])){
			return array( 
					'FIELDSSTR'=>substr($strFields,2),
					'VALUEARR'=>$arrValues 
			);
		}else{
			throw new Exception('ORM is illegally.');
			return false;
		}
	}

	/**
	 * 判断是否为自运算
	 * @param string $p_strField
	 * @param mix $p_mixValue
	 * @param string $o_strOperator
	 * @param int $o_intParam
	 * @return true/false
	 */
	private static function _isSelfOperate($p_strField,$p_mixValue,&$o_strOperator,&$o_intParam){
		$strPattern='/^'.$p_strField.'([+\-*\/])(\d+)/i';
		$arrResult=array();
		if(1==preg_match($strPattern,$p_mixValue,$arrResult)){
			$o_strOperator=$arrResult[1];
			$o_intParam=$arrResult[2];
			return true;
		}else{
			return false;
		}
	}

	/**
	 * 重新生成新的主键列表
	 * @param array $p_mixIDs
	 * @return array
	 */
	private static function _rebuildPKIDs($p_mixIDs,$p_strPKField){
		if(is_array($p_mixIDs)){
			if(empty($p_mixIDs)){
				return array();
			}else{
				$arrPKIDs=array();
				foreach($p_mixIDs as $arrIDs){
					$arrPKIDs[]=$arrIDs[$p_strPKField];
				}
				return array_unique($arrPKIDs);
			}
		}else{
			return array_unique(explode(',',$p_mixIDs));
		}
	}

	/**
	 * 根据主键数据生成where条件
	 * @param string $p_strPKIDField
	 * @param array $p_arrData
	 * @return array
	 */
	private static function _joinPKWhereString($p_strPKIDField,$p_arrData){
		if(isset($p_arrData[$p_strPKIDField])){
			return array( 
					'FIELDSSTR'=>$p_strPKIDField.'='.self::$_strBindHolder.$p_strPKIDField,
					'VALUEARR'=>array( 
							$p_strPKIDField=>$p_arrData[$p_strPKIDField] 
					) 
			);
		}else{
			throw new Exception('You missed ORM PKID('.$p_strPKIDField.').');
			return false;
		}
	}

	/**
	 * 获取数据库表结构缓存key
	 * @param string $p_strORMName
	 * @param string $p_strTblName
	 * @return string
	 */
	private static function _getTblFieldCacheKey($p_strORMName,$p_strTblName){
		return $p_strORMName.'_tblfield_'.$p_strTblName;
	}

	/**
	 * 获取ORM数据缓存Key
	 * @param string $p_strORMName
	 * @param string $p_strTblName
	 * @param string $p_strPKIDField
	 * @param int $p_intPKID
	 * @return string
	 */
	private static function _getCacheRowKey($p_strORMName,$p_strTblName,$p_strPKIDField,$p_intPKID){
		return $p_strORMName.'_r_'.$p_strTblName.'_'.$p_strPKIDField.'_'.$p_intPKID;
	}

	/**
	 * 生成cache的数据
	 * @param mix $p_mixValue
	 * @param int $p_intLifeTime
	 * @return array
	 */
	private static function _implodeCache($p_mixValue,$p_intLifeTime){
		return array( 
				'DATA'=>$p_mixValue,
				'CREATETIME'=>$_SERVER['REQUEST_TIME'],
				'LIFETIME'=>$p_intLifeTime 
		);
	}
}